#include "jmetatype.h"

namespace JXQ
{

class J_DECL_HIDDEN TypeInfoPrivate
{
public:
	inline TypeInfoPrivate(const std::type_info &info, size_t size,
						   bool isPrimitive, bool isFloat, bool isPointer) :
		info(info), size(size), isPrimitive(isPrimitive),
		isFloat(isFloat), isPointer(isPointer) {}

	const std::type_info& info;
	size_t size;
	bool isPrimitive;
	bool isFloat;
	bool isPointer;
};

/*-----------------------------------------------------------------------------------*/

JTypeInfo::JTypeInfo(const std::type_info &info, size_t size, bool isPrimitive,
					 bool isFloat, bool isPointer) :
	d_ptr(new TypeInfoPrivate(info, size, isPrimitive, isFloat, isPointer))
{

}

JTypeInfo::~JTypeInfo()
{
	delete d_ptr;
}

std::string JTypeInfo::name() const
{
	return ABI_CXA_DEMANGLE(d_ptr->info.name());
}

size_t JTypeInfo::size() const
{
	return d_ptr->size;
}

bool JTypeInfo::isPrimitive() const
{
	return d_ptr->isPrimitive;
}

bool JTypeInfo::isFloat() const
{
	return d_ptr->isFloat;
}

bool JTypeInfo::isPointer() const
{
	return d_ptr->isPointer;
}

bool JTypeInfo::operator==(const JTypeInfo& info) const
{
	return d_ptr->info == info.d_ptr->info;
}

bool JTypeInfo::operator!=(const JTypeInfo& info) const
{
	return d_ptr->info != info.d_ptr->info;
}

bool JTypeInfo::operator==(const std::type_info &info) const
{
	return d_ptr->info == info;
}

bool JTypeInfo::operator!=(const std::type_info &info) const
{
	return d_ptr->info != info;
}

const std::type_info& JTypeInfo::stdTypeInfo() const
{
	return d_ptr->info;
}

// 数据结构全部使用哈希，尽可能的提高性能

const JTypeInfo JTypeInfo::voidType(typeid(void), 0, false, false, false);

JTypeInfo::TypeIdHash JTypeInfo::typeIdHash
{
	{
		"void",
		typeid(void).hash_code()
	}
};

JTypeInfo::TypeInfoHash JTypeInfo::typeInfoHash
{
	{
		typeid(void).hash_code(),
		new JTypeInfo(typeid(void), 0, false, false, false)
	}
};

/*-----------------------------------------------------------------------------------*/

JOtherMethodHash::CopyMethodHash
JOtherMethodHash::copyMethodHash;

void JOtherMethodHash::registerCopyMethod(size_t id, CopyMethod &&method)
{
	copyMethodHash.emplace(id, std::forward<CopyMethod>(method));
}

static std::function<void(void*,const void*)> copyNULL = nullptr;

JOtherMethodHash::CopyMethod &JOtherMethodHash::findCopyMethod(size_t id)
{
	auto it = copyMethodHash.find(id);
	if( it == copyMethodHash.end() )
	{
		jError() << "Unable to copy object, unable to find copy method: type id =" << id;
		return copyNULL;
	}
	return it->second;
}

JOtherMethodHash::CopyConstructMethodHash
JOtherMethodHash::copyConstructMethodHash;

void JOtherMethodHash::
registerCopyConstructMethod(size_t id, CopyConstructMethod &&method)
{
	copyConstructMethodHash.emplace(id, std::forward<CopyConstructMethod>(method));
}

static std::function<void*(const void*)> copyConstructNULL = nullptr;

JOtherMethodHash::CopyConstructMethod &JOtherMethodHash::
findCopyConstructMethod(size_t id)
{
	auto it = copyConstructMethodHash.find(id);
	if( it == copyConstructMethodHash.end() )
	{
		jError() << "Unable to copy construct object, unable to find copy construct method: type id =" << id;
		return copyConstructNULL;
	}
	return it->second;
}

JOtherMethodHash::DestructMethodHash
JOtherMethodHash::destructMethodHash;

void JOtherMethodHash::
registerDestructMethod(size_t id, DestructMethod &&method)
{
	destructMethodHash.emplace(id, std::forward<DestructMethod>(method));
}

static std::function<void(const void*)> destructNULL = nullptr;

JOtherMethodHash::DestructMethod &JOtherMethodHash::
findDestructMethod(size_t id)
{
	auto it = destructMethodHash.find(id);
	if( it == destructMethodHash.end() )
	{
		jError() << "Unable to destruct object, destructor method not found: type id =" << id;
		return destructNULL;
	}
	return it->second;
}

/*-----------------------------------------------------------------------------------*/



} //namespace JXQ
